package com.hsylient.springboot.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.hsylient.springboot.request.PostRequest;
import com.hsylient.springboot.request.ValidateRequest;
import com.hsylient.springboot.response.RequestMethodResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;

@Slf4j
@RestController
@Tag(name = "swagger+请求方式测试", description = "swagger测试+请求方式测试")
public class RequestMethodController {

    /**
     * GET请求中参数不能为空，springboot自动校验
     */
    @Operation(summary = "GET请求-单个参数")
    @GetMapping("/v1/request/method/get/param/single")
    public String singleParam(@RequestParam("param") String param) {
        // springboot只能校验参数是否为空，但是不能校验参数是否是空白字符串
        if (StrUtil.isBlank(param)) return "参数为空白字符串";
        log.info("[GET请求方式测试] 单个请求参数 {}", param);
        return "success";
    }


    @Operation(summary = "GET请求-多个参数")
    @GetMapping("/v1/request/method/get/param/multiple")
    public String multipleParam(@RequestParam("user_name") String name,
                                @RequestParam(required = false) Integer age,
                                @RequestParam BigDecimal salary) {
        log.info("[GET请求方式测试] 多个请求参数 姓名：{} 年龄：{}, 薪水：{}", name, age, salary);
        return "success";
    }

    @Operation(summary = "GET请求-路径参数")
    @GetMapping("/v1/request/method/get/param/{pathParam}")
    public String pathParam(@PathVariable String pathParam) {
        log.info("[GET请求方式测试] 路径参数 {}", pathParam);
        return "success";
    }

    @Operation(summary = "GET请求-返回响应体")
    @Parameters({
            @Parameter(name = "user_name", description = "用户名", in = ParameterIn.PATH),
            @Parameter(name = "age", description = "年龄", required = true, in = ParameterIn.HEADER),
            @Parameter(name = "salary", description = "薪水", in = ParameterIn.QUERY),
            @Parameter(name = "birthday", description = "生日", in = ParameterIn.QUERY)
    })
    @GetMapping("/v1/request/method/get/return/body/{user_name}")
    public RequestMethodResponse returnBody(@PathVariable("user_name") String name,
                                            @RequestHeader Integer age,
                                            @RequestParam(required = false) BigDecimal salary,
                                            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime birthday) {
        log.info("[GET请求方式测试] 多个请求参数 姓名：{} 年龄：{}, 薪水：{}, 生日：{}", name, age, salary, birthday);
        // 响应体组装
        RequestMethodResponse response = new RequestMethodResponse();
        response.setId(1L);
        response.setName(name);
        response.setSalary(salary);
        response.setBirthday(birthday);
        return response;
    }


    /**
     * POST请求中的时间参数需要使用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")来处理
     * GET请求中的时间参数需要使用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")来处理
     */
    @Operation(summary = "POST请求-传递请求体")
    @PostMapping("/v1/request/method/post/body")
    public String postMessage(@RequestBody PostRequest postRequest) {
        log.info("[POST请求测试] 使用请求体的方式 打印请求体中的内容 {}", JSON.toJSONString(postRequest));
        return "success";
    }


    @Operation(summary = "POST请求-参数校验")
    @PostMapping("/v1/request/method/post/param/check")
    public String getMessage(@RequestBody @Valid ValidateRequest request) {
        log.info("[POST请求测试] 参数校验 {}", JSON.toJSONString(request));
        return "hello";
    }


    /**
     * 测试在Get请求中是否可以使用对象接收参数，发现是可以接收成功的。
     * ParameterObject注解的作用是将swagger参数展开
     * 如果不用这个参数 springdoc.default-flat-param-object = true (全局配置)
     * 同时开启配置和使用注解@ParameterObject也不会有问题
     */
    @Operation(summary = "GET请求-传递对象参数")
    @GetMapping("/v1/request/method/get/body")
    public void pullMessage(@ParameterObject PostRequest postRequest) {
//    public void pullMessage(PostRequest postRequest) {
        log.info("[GET请求测试] 测试get请求传请求体 {}", JSON.toJSONString(postRequest));
    }


    /**
     * post请求可以使用url传参
     */
    @Operation(summary = "POST请求-传递请求参数")
    @PostMapping("/v1/request/method/post/param")
    public void pushMessage(@RequestParam("id") Long id,
                            @RequestParam("username") String username,
                            String exceptionReason) {
        log.info("id = {}, username = {}", id, username);
        log.info("原因：{}", exceptionReason);
    }


    @Operation(summary = "GET请求-测试header是否为空")
    @GetMapping("/v1/request/header")
    public void header(@RequestHeader(value = "userId", required = false) Long userId) {
        log.info("[用户ID] {}", userId);
    }
}
